package cn.ac.big.bigd.service;

import cn.ac.big.bigd.api.controller.SubmitController;
import cn.ac.big.bigd.constant.ResultStatus;
import cn.ac.big.bigd.dto.Result;
import cn.ac.big.bigd.model.submit.ChromosomeAssignmentInfo;
import cn.ac.big.bigd.model.submit.OrganellaAssignmentInfo;
import cn.ac.big.bigd.model.submit.PlasmidAssignmentInfo;
import cn.ac.big.bigd.model.submit.Submission;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.Arrays;
import java.util.List;

/**
 * Created by wangfan on 2017/5/26.
 */

@Service
public class ScriptService {

    private static final Logger logger = LoggerFactory.getLogger(ScriptService.class);

    /**
     * @param submission
     * @param outdir     输出目录
     * @param outPath    输出脚本全路径
     * @return
     */
    public boolean outQcScript(Submission submission, String outdir, String outPath) {
        try {
            PrintWriter pw = new PrintWriter(new FileWriter(outPath));
            String name = submission.getMissionId();
            int assemblyLevel = submission.getFiles().getAssemblyLevel() + 1;
            String q;
            String annotation = "";
            String AGPc2s = "";
            String AGPs2chr = "";
            String AGPc2x = "";
            boolean hasAnnotation = (null != submission.getFiles().getAnnotationFilename());
            boolean hasAGPc2s = (null != submission.getFiles().getScaffoldsFromContigsFilename());
            boolean hasAGPs2chr = (null != submission.getFiles().getChroFromScaffoldsFilename());
            boolean hasAGPc2x = (null != submission.getFiles().getChroFromContigsFilename());
            int chromsomeFrom = submission.getFiles().getChromsomeFrom();
            logger.info("submission.getFiles().getSubmissionWay()" + submission.getFiles().getSubmissionWay());

            q = outdir + "" + submission.getFiles().getSequenceFilename();
            if (hasAnnotation) {
                annotation = outdir + "" + submission.getFiles().getAnnotationFilename();
            }
            if (hasAGPc2s) {
                AGPc2s = outdir + "" + submission.getFiles().getScaffoldsFromContigsFilename();
            }
            if (hasAGPs2chr) {
                AGPs2chr = outdir + "" + submission.getFiles().getChroFromScaffoldsFilename();
            }
            if (hasAGPc2x) {
                AGPc2x = outdir + "" + submission.getFiles().getChroFromContigsFilename();
            }


            logger.info("hehe");
            String submissionID = submission.getMissionId();

            pw.println("#!/bin/sh");
            pw.println("#PBS -q batch");
            pw.println("#PBS -N " + submission.getMissionId());
            pw.println("#PBS -e " + outdir + "" + submissionID + ".log");
            pw.println("#PBS -o " + outdir + "" + submissionID + ".out");
            pw.println("#PBS -l mem=16gb,walltime=24:00:00,nodes=1:ppn=6");
            pw.println("#HSCHED -s hschedd");
            pw.println("cd /disk2/gwhfileprocess/" + submissionID + "/");


            String str = "";

            logger.info("judge");
            if (assemblyLevel == 3 && chromsomeFrom == 0) {//系统中的Assembly level for the AGP file中的选择为contig->scaffold->chromosome

                logger.info("assembly level for the AGP file------contig->scaffold->chromosome");
                str = "perl /disk2/software/QCprogram20170518/CheckFilesCtg2scaf2chrv1.pl"
                        + " -name " + name
                        + " -assemblylevel " + assemblyLevel
                        + " -q \"" + q+"\"";
                if (hasAnnotation) {
                    str = str + " -annotation \"" + annotation+"\"";
                }
                if (submission.getFiles().getAgpFile() == 1) {
                    str = str + " -AGPc2s \"" + AGPc2s+"\"";
                    str = str + " -AGPs2chr \"" + AGPs2chr+"\"";

                }

            } else {
                logger.info("assembly level for the AGP file------else");
                str = "perl /disk2/software/QCprogram20170518/CheckFilesCtg2xv1.pl"
                        + " -name " + name
                        + " -assemblylevel " + assemblyLevel
                        + " -q \"" + q+"\"";
                if (hasAnnotation) {
                    str = str + " -annotation \"" + annotation+"\"";
                }
                if (assemblyLevel == 3 && chromsomeFrom == 1) {
                    if (submission.getFiles().getAgpFile() == 1) {
                        str = str + " -AGPc2x \"" + AGPc2x+"\"";
                    }
                }
                if (assemblyLevel == 2) {
                    if (submission.getFiles().getAgpFile() == 1) {
                        str = str + " -AGPc2x \"" + AGPc2s+"\"";
                    }
                }
            }


            if (null != submission.getAssignment().getRepresentGaps() && submission.getAssignment().getRepresentGaps() && "Estimated length".equals(submission.getAssignment().getGapLengthType()) && submission.getAssignment().getMinimumGapLength() > 0) {
                str = str + " -Nlen " + submission.getAssignment().getMinimumGapLength();
            } else {
                str = str + " -Nlen  10 ";
            }
            str = str + " -o " + outdir;


            if (submission.getAssignment().getChromosomeAssigned()) {

                if (submission.getAssignment().getChromosomeUpload()) {
                    str = str + " -csvchr " + outdir + "" + submission.getAssignment().getChromosomeFilename();
                } else {
                    File file = new File(outdir + "temp.chr.csv");
                    if (file.exists()) {
                        file.delete();
                    }
                    file.createNewFile();
                    BufferedWriter out = new BufferedWriter(new FileWriter(file));
                    out.write("Sequence ID,Chromosome name,Complete,Circular\r\n"); // \r\n即为换行
                    List<ChromosomeAssignmentInfo> list = submission.getAssignment().getChromosomeAssignmentInfoList();
                    for (ChromosomeAssignmentInfo chromosomeAssignmentInfo : list) {
                        String string = chromosomeAssignmentInfo.getSequenceId() + "," + chromosomeAssignmentInfo.getChromosomeName() + ",";
                        if (chromosomeAssignmentInfo.getComplete()) {
                            string = string + "TRUE" + ",";
                        } else {
                            string = string + "FALSE" + ",";
                        }
                        if (chromosomeAssignmentInfo.getCircular()) {
                            string = string + "TRUE";
                        } else {
                            string = string + "FALSE";
                        }
                        out.write(string + "\r\n");


                    }
                    out.flush(); // 把缓存区内容压入文件
                    out.close(); // 最后记得关闭文件

                    str = str + " -csvchr " + outdir + "temp.chr.csv";

                }

            }

            if (submission.getAssignment().getPlasmidAssigned()) {

                if (submission.getAssignment().getPlasmidUpload()) {
                    str = str + " -csvplasmid " + outdir + "" + submission.getAssignment().getPlasmidFilename();
                } else {
                    File file = new File(outdir + "temp.plasmid.csv");
                    if (file.exists()) {
                        file.delete();
                    }
                    file.createNewFile();
                    BufferedWriter out = new BufferedWriter(new FileWriter(file));
                    out.write("Sequence ID,Plasmid name,Complete,Circular\r\n"); // \r\n即为换行
                    List<PlasmidAssignmentInfo> list = submission.getAssignment().getPlasmidAssignmentInfoList();
                    for (PlasmidAssignmentInfo plasmidAssignmentInfo : list) {
                        String string = plasmidAssignmentInfo.getSequenceId() + "," + plasmidAssignmentInfo.getPlasmidName() + ",";
                        if (plasmidAssignmentInfo.getComplete()) {
                            string = string + "TRUE" + ",";
                        } else {
                            string = string + "FALSE" + ",";
                        }
                        if (plasmidAssignmentInfo.getCircular()) {
                            string = string + "TRUE";
                        } else {
                            string = string + "FALSE";
                        }
                        out.write(string + "\r\n");


                    }
                    out.flush(); // 把缓存区内容压入文件
                    out.close(); // 最后记得关闭文件

                    str = str + " -csvplasmid " + outdir + "temp.plasmid.csv";

                }

            }


            if (submission.getAssignment().getOrganellaAssigned()) {

                if (submission.getAssignment().getOrganellaUpload()) {
                    str = str + " -csvorganella " + outdir + "" + submission.getAssignment().getOrganellaFilename();
                } else {
                    File file = new File(outdir + "temp.organella.csv");
                    if (file.exists()) {
                        file.delete();
                    }
                    file.createNewFile();
                    BufferedWriter out = new BufferedWriter(new FileWriter(file));
                    out.write("Sequence ID,Type,Complete,Circular\r\n"); // \r\n即为换行
                    List<OrganellaAssignmentInfo> list = submission.getAssignment().getOrganellaAssignmentInfoList();
                    for (OrganellaAssignmentInfo organellaAssignmentInfo : list) {
                        String string = organellaAssignmentInfo.getSequenceId() + "," + organellaAssignmentInfo.getType() + ",";
                        if (organellaAssignmentInfo.getComplete()) {
                            string = string + "TRUE" + ",";
                        } else {
                            string = string + "FALSE" + ",";
                        }
                        if (organellaAssignmentInfo.getCircular()) {
                            string = string + "TRUE";
                        } else {
                            string = string + "FALSE";
                        }
                        out.write(string + "\r\n");


                    }
                    out.flush(); // 把缓存区内容压入文件
                    out.close(); // 最后记得关闭文件

                    str = str + " -csvorganella " + outdir + "temp.organella.csv";

                }

            }


//            str =str+" > "+outdir+""+submissionID+".log";


            logger.info("STR----" + str);
            pw.println(str);
            if (submission.getFiles().isCheckProcesses()) {
          /*      pw.println("python /disk2/software/QCprogram20170518/Gwh_Check_V2.py"
                        + " -name " + submission.getMissionId()
                        + " -t /disk2/software/QCprogram20170518/UniVec_db/UniVec"
                        + " -q " + q
                        + " -o " + outdir
                );*/

                pw.println("perl /disk2/software/QCprogram20170518/QC_Contamination.pl"
                        + " -name " + submission.getMissionId()
                        + " -t /disk2/software/QCprogram20170518/UniVec_db/UniVec"
                        + " -q \"" + q+"\""
                        + " -o " + outdir
                );
            }
            pw.println("echo \"DoneFinished!\"");
            pw.close();
            return true;
        } catch (Exception e) {
            logger.info(e.toString());
            return false;
        }
    }

    public boolean outStatsScript(Submission submission, String outdir, String outPath) {
        try {
            PrintWriter pw = new PrintWriter(new FileWriter(outPath));
            String name = submission.getAccession();
            String accession = name;


            int assemblyLevel = submission.getFiles().getAssemblyLevel() + 1;
            String genome;
            String annotation = "";
            boolean hasAnnotation = (null != submission.getFiles().getAnnotationFilename());

            int chromsomeFrom = submission.getFiles().getChromsomeFrom();
            logger.info("submission.getFiles().getSubmissionWay()" + submission.getFiles().getSubmissionWay());
            if (submission.getFiles().getSubmissionWay().equals("ftp")) {
                genome = outdir + "" + submission.getFiles().getSequenceFilename();
                if (hasAnnotation) {
                    annotation = outdir + "" + submission.getFiles().getAnnotationFilename();
                }


            } else {
                logger.info("online");
                genome = outdir + "" + new File(submission.getFiles().getSequenceFilepath()).getName();
                if (hasAnnotation) {
                    annotation = outdir + "" + new File(submission.getFiles().getAnnotationFilepath()).getName();
                }
            }
            String submissionID = submission.getMissionId();
            pw.println("#!/bin/sh");
            pw.println("#PBS -q batch");
            pw.println("#PBS -N " + name);
            pw.println("#PBS -e " + outdir + "" + name + ".log");
            pw.println("#PBS -o " + outdir + "" + name + ".out");
            pw.println("#PBS -l mem=16gb,walltime=24:00:00,nodes=1:ppn=6");
            pw.println("#HSCHED -s hschedd");
            pw.println("cd /disk2/gwhfileprocess/" + submissionID + "/");


            String str = "perl /disk2/software/stats/stats0707.pl"
                    + " -name " + name
                    + " -assemblylevel " + assemblyLevel
                    + " -accession " + accession
                    + " -genome " + genome;
            if (hasAnnotation) {
                str = str + " -annotation " + annotation;
            }


            if (submission.getAssignment().getChromosomeAssigned()) {

                if (submission.getAssignment().getChromosomeUpload()) {
                    str = str + " -csvchr " + outdir + "\"" + submission.getAssignment().getChromosomeFilename()+"\"";
                } else {
                    File file = new File(outdir + "temp.chr.csv");
                    if (file.exists()) {
                        file.delete();
                    }
                    file.createNewFile();
                    BufferedWriter out = new BufferedWriter(new FileWriter(file));
                    out.write("Sequence ID,Chromosome name,Complete,Circular\r\n"); // \r\n即为换行
                    List<ChromosomeAssignmentInfo> list = submission.getAssignment().getChromosomeAssignmentInfoList();
                    for (ChromosomeAssignmentInfo chromosomeAssignmentInfo : list) {
                        String string = chromosomeAssignmentInfo.getSequenceId() + "," + chromosomeAssignmentInfo.getChromosomeName() + ",";
                        if (chromosomeAssignmentInfo.getComplete()) {
                            string = string + "TRUE" + ",";
                        } else {
                            string = string + "FALSE" + ",";
                        }
                        if (chromosomeAssignmentInfo.getCircular()) {
                            string = string + "TRUE";
                        } else {
                            string = string + "FALSE";
                        }
                        out.write(string + "\r\n");


                    }
                    out.flush(); // 把缓存区内容压入文件
                    out.close(); // 最后记得关闭文件

                    str = str + " -csvchr " + outdir + "temp.chr.csv";

                }

            }

            if (submission.getAssignment().getPlasmidAssigned()) {

                if (submission.getAssignment().getPlasmidUpload()) {
                    str = str + " -csvplasmid " + outdir + "" + submission.getAssignment().getPlasmidFilename();
                } else {
                    File file = new File(outdir + "temp.plasmid.csv");
                    if (file.exists()) {
                        file.delete();
                    }
                    file.createNewFile();
                    BufferedWriter out = new BufferedWriter(new FileWriter(file));
                    out.write("Sequence ID,Plasmid name,Complete,Circular\r\n"); // \r\n即为换行
                    List<PlasmidAssignmentInfo> list = submission.getAssignment().getPlasmidAssignmentInfoList();
                    for (PlasmidAssignmentInfo plasmidAssignmentInfo : list) {
                        String string = plasmidAssignmentInfo.getSequenceId() + "," + plasmidAssignmentInfo.getPlasmidName() + ",";
                        if (plasmidAssignmentInfo.getComplete()) {
                            string = string + "TRUE" + ",";
                        } else {
                            string = string + "FALSE" + ",";
                        }
                        if (plasmidAssignmentInfo.getCircular()) {
                            string = string + "TRUE";
                        } else {
                            string = string + "FALSE";
                        }
                        out.write(string + "\r\n");


                    }
                    out.flush(); // 把缓存区内容压入文件
                    out.close(); // 最后记得关闭文件

                    str = str + " -csvplasmid " + outdir + "temp.plasmid.csv";

                }

            }


            if (submission.getAssignment().getOrganellaAssigned()) {

                if (submission.getAssignment().getOrganellaUpload()) {
                    str = str + " -csvorganella " + outdir + "" + submission.getAssignment().getOrganellaFilename();
                } else {
                    File file = new File(outdir + "temp.organella.csv");
                    if (file.exists()) {
                        file.delete();
                    }
                    file.createNewFile();
                    BufferedWriter out = new BufferedWriter(new FileWriter(file));
                    out.write("Sequence ID,Type,Complete,Circular\r\n"); // \r\n即为换行
                    List<OrganellaAssignmentInfo> list = submission.getAssignment().getOrganellaAssignmentInfoList();
                    for (OrganellaAssignmentInfo organellaAssignmentInfo : list) {
                        String string = organellaAssignmentInfo.getSequenceId() + "," + organellaAssignmentInfo.getType() + ",";
                        if (organellaAssignmentInfo.getComplete()) {
                            string = string + "TRUE" + ",";
                        } else {
                            string = string + "FALSE" + ",";
                        }
                        if (organellaAssignmentInfo.getCircular()) {
                            string = string + "TRUE";
                        } else {
                            string = string + "FALSE";
                        }
                        out.write(string + "\r\n");


                    }
                    out.flush(); // 把缓存区内容压入文件
                    out.close(); // 最后记得关闭文件

                    str = str + " -csvorganella " + outdir + "temp.organella.csv";

                }

            }



            boolean hasAGPc2s = (null != submission.getFiles().getScaffoldsFromContigsFilename());
            boolean hasAGPs2chr = (null != submission.getFiles().getChroFromScaffoldsFilename());
            boolean hasAGPc2x = (null != submission.getFiles().getChroFromContigsFilename());



            if(hasAGPc2s){
                str = str + " -AGPc2s " + outdir + "" + submission.getFiles().getScaffoldsFromContigsFilename();
            }
            if (hasAGPs2chr) {
                str = str + " -AGPs2chr " +outdir + "" + submission.getFiles().getChroFromScaffoldsFilename();
            }
            if (hasAGPc2x) {
                str = str + " -AGPc2x "+ outdir + "" + submission.getFiles().getChroFromContigsFilename();
            }

            str = str + " -o " + outdir;


            logger.info("STR----" + str);
            pw.println(str);
            pw.println("echo \"DoneFinished!\"");
            pw.close();
            return true;
        } catch (Exception e) {
            logger.info(e.toString());
            return false;
        }
    }
    public boolean outFormatScript(Submission submission, String outdir, String outPath) {
        try {
            PrintWriter pw = new PrintWriter(new FileWriter(outPath));
            String name = submission.getAccession();
            String accession = name;
            String submissionID = submission.getMissionId();
            pw.println("#!/bin/sh");
            pw.println("#PBS -q batch");
            pw.println("#PBS -N " + name+"format");
            pw.println("#PBS -e " + outdir + "" + name + ".formatlog");
            pw.println("#PBS -o " + outdir + "" + name + ".formatout");
            pw.println("#PBS -l mem=4gb,walltime=24:00:00,nodes=1:ppn=1");
            pw.println("#HSCHED -s hschedd");
            pw.println("cd /disk2/gwhfileprocess/" + submissionID + "/");
            String str = "perl /disk2/software/stats/format2display.pl"
                    + " -out " + accession+".formatfeature";
            String savePath = "/disk2/gwhfileprocess/" + submission.getMissionId() + "/";
            str = str + " -genome  " + savePath+accession+".genome.fasta";
            File f =new File(savePath+submission.getAccession() + ".feature");
            if(f.exists()){
                str = str + " -feature  " + savePath+accession+".feature";
            }
        /*    f =new File(savePath+submission.getAccession() + ".Protein.faa");
            if(f.exists()){
                str = str + " -Protein " + savePath+accession+".Protein.faa";
            }*/
            f =new File(savePath+submission.getAccession() + ".RNA.fasta");
            if(f.exists()){
                str = str + " -RNA  " + savePath+accession+".RNA.fasta";
            }
            f =new File(savePath+submission.getAccession() + ".CDS.fasta");
            if(f.exists()){
                str = str + " -CDS    " + savePath+accession+".CDS.fasta ";
            }
            f =new File(savePath+submission.getAccession() + ".Protein.faa");
            if(f.exists()){
                str = str + " -Protein   " + savePath+accession+".Protein.faa";
            }
            logger.info("STR----" + str);
            pw.println(str);
            pw.println("echo \"DoneFinished!\"");
            pw.close();
            return true;
        } catch (Exception e) {
            logger.info(e.toString());
            return false;
        }
    }
//    public boolean execProcess(String[] args) {
//        try {
//            Process pr = Runtime.getRuntime().exec(args);
//
//            BufferedInputStream in = new BufferedInputStream(pr.getInputStream());
//            BufferedReader br = new BufferedReader(new InputStreamReader(in));
//            String line;
//            while ((line = br.readLine()) != null) {
//                logger.info("--- " + line);
//      /*          Pattern statusPattern = Pattern.compile("[1-9]\\d*\\.gsaftp.*");
//                if (statusPattern.matcher(line).matches()) {
//                    String[] strArr = line.split("\\s+");
//                    for (String str : strArr) {
//                        System.out.println(str);
//                    }
//
//                }*/
//            }
//            br.close();
//            in.close();
//            pr.waitFor();
//            pr.destroy();
//
//
//        } catch (Exception e) {
//            e.printStackTrace();
//            return false;
//        }
//        return true;
//    }

    public String getProcessJobId(String[] args) {
       String jobId =null;
        try {
            Process pr = Runtime.getRuntime().exec(args);
            BufferedInputStream in = new BufferedInputStream(pr.getInputStream());
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String line;
            while ((line = br.readLine()) != null) {
                logger.info("--- " + line);
                if(!line.contains("+++")){
                    jobId=line.trim();
                }
      /*          Pattern statusPattern = Pattern.compile("[1-9]\\d*\\.gsaftp.*");
                if (statusPattern.matcher(line).matches()) {
                    String[] strArr = line.split("\\s+");
                    for (String str : strArr) {
                        System.out.println(str);
                    }

                }*/
            }
            logger.info("jobId " + jobId);
            br.close();
            in.close();
            pr.waitFor();
            pr.destroy();


        } catch (Exception e) {
            e.printStackTrace();
        }
        return jobId;

    }



    public boolean isDsubJobFinished(String jobId, String savePath) {
//        String[] command = new String[]{"/bin/sh", "-c", "qstat | grep " + jobName};
        String[] command = new String[]{"/bin/sh", "-c", "mstat -j " + jobId};
//        String[] command = new String[]{"mstat -j " + jobId};
        logger.info("judge job finish or not:"+ Arrays.toString(command));
        String cmm =Arrays.toString(command);
        while (true) {
            try {
                Process pr = Runtime.getRuntime().exec(command, null, new File(savePath));
                BufferedInputStream in = new BufferedInputStream(pr.getInputStream());
                BufferedReader br = new BufferedReader(new InputStreamReader(in));
                String str = "";
                String line;
                while ((line = br.readLine()) != null) {
                    str = str + line;
                }
                logger.info("str----:  "+str);
                if (str.contains("qstat: Unknown Job Id Error")||str.isEmpty()||null==str) {
                    logger.info("finish");
                    break;  // 跳离循环
                }
                br.close();
                in.close();
                pr.waitFor();
                pr.destroy();

            } catch (Exception e) {
                logger.info(e.toString());
                return false;
            }
        }
        return true;
    }

}
